﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.Research.Kinect.Nui;
using MSUS.Kinect.SkeletonTracker;
using System.Windows.Controls;
using System.Windows.Input;
using System.Collections.ObjectModel;
using Microsoft.Office.Interop.PowerPoint;
using System.Diagnostics;


namespace MSUS.Kinect.PowerPointController.ViewModels
{

	public class MainViewModel : ViewModelBase, IDisposable
	{

		#region Properties

		private KinectController controller;

		public string LastGesture { get; set; }
		public int GestureCounter { get; set; }
		public ObservableCollection<string> LoadedGestures { get; private set; }
		public bool NoSkeletonTrackedWarning { get; set; }
		public bool UseSimpleKeyboardCommands { get; set; }
		public bool HandOnLeftHip { get; set; }
	    public Microsoft.Office.Interop.PowerPoint.Application PowerPointApplication { get; set; }
		public string ApplicationStartupPath { get; set; }
	    
		private JointID _currentTrackedJoint;
		public JointID CurrentTrackedJoint 
		{
			get
			{
				return _currentTrackedJoint;
			}
			set
			{
				_currentTrackedJoint = value;
				OnPropertyChanged(()=> CurrentTrackedJoint);
				CurrentTrackedJointName = _currentTrackedJoint.ToString();
				OnPropertyChanged(()=> CurrentTrackedJointName);
			}
		}
		public string CurrentTrackedJointName { get; set; }


		private bool _mouseTrackingActive;
		public bool MouseTrackingActive 
		{
			get
			{
				return _mouseTrackingActive;
			}
			set
			{
				if (_mouseTrackingActive != value)
				{
					_mouseTrackingActive = value;
					OnPropertyChanged(() => MouseTrackingActive);
				}
			}
		}


		private bool _enableMouseTracking;
		public bool EnableMouseTracking 
		{
			get
			{
				return _enableMouseTracking;
			}
			set
			{
				if (_enableMouseTracking != value)
				{
					_enableMouseTracking = value;
					OnPropertyChanged(() => EnableMouseTracking);
				}
			}
		}

	    #endregion

		public MainViewModel()
		{
			LoadedGestures = new ObservableCollection<string> {"No Gestures Loaded"};
		    UseSimpleKeyboardCommands = false;
			MouseTrackingActive = false;
			EnableMouseTracking = false;


			controller = new KinectController();
			CurrentTrackedJoint = controller.CurrentJointId;

			controller.AddJointProximityTrigger(new JointProximityTrigger {JointA = JointID.HipLeft, JointB = JointID.HandLeft, dist = 0.25f});
			controller.AddJointProximityTrigger(new JointProximityTrigger {JointA = JointID.ShoulderRight, JointB = JointID.HandLeft, dist = 0.25f });

		    Assembly assembly = Assembly.GetExecutingAssembly();
            // strip the file:/// uri definition as it will cause an exception later on
		    string directoryName = Path.GetDirectoryName(assembly.CodeBase.Replace("file:///", string.Empty)); 

            // TODO Figure out how to do this nicely
            controller.GesturePath = Path.Combine(directoryName, "Gestures");
			controller.GesturesLoaded += controller_GesturesLoaded;
			controller.GestureRecognised += controller_GestureRecognised;
			controller.TrackingWarningChanged += controller_TrackingWarningChanged;
			controller.MouseMove += controller_MouseMove;
			controller.JointProximityTriggerChanged += controller_JointProximityTriggerChanged;
			controller.TrackedJointChanged += controller_TrackedJointChanged;
		}


		public void Begin(Canvas mainCanvas, Image fullTrackingImage, Image handTrackingImage)
		{
			controller.MainCanvas = mainCanvas;
			controller.FullTrackingImage = fullTrackingImage;
			controller.HandTrackingImage = handTrackingImage;

			controller.Begin();
		}

		public void Dispose()
		{
			if (controller != null)
				controller.Dispose();
		}


		#region Event Handlers

		void controller_MouseMove(int x, int y)
		{
			if (MouseTrackingActive)
			{
				Win32.SetCursorPos(x, y);
			}
		}


		public void OnKeyDown(Key key)
		{
			controller.OnKeyDown(key);
		}

		void controller_TrackingWarningChanged(bool trackingWarning)
		{
			NoSkeletonTrackedWarning = trackingWarning;
			OnPropertyChanged(() => NoSkeletonTrackedWarning);
		}

		void controller_GestureRecognised(string gestureName)
		{
			LastGesture = gestureName;
			GestureCounter++;
			OnPropertyChanged(() => LastGesture);
			OnPropertyChanged(() => GestureCounter);

			if (UseSimpleKeyboardCommands)
			{
				//	simple keyboard left/right commands
				switch (gestureName.ToLower())
				{
					case "breaststrokeright":
						System.Windows.Forms.SendKeys.SendWait("{Down}");
						break;
					case "breaststrokeleft":
						System.Windows.Forms.SendKeys.SendWait("{Up}");
						break;
					case "salute":
						EnableMouseTracking = !EnableMouseTracking;
						if (!EnableMouseTracking && MouseTrackingActive)
						{
							MouseTrackingActive = false;
						}
						break;
					case "waxoff":
					case "waxon":
					case "flapdownright":
					case "flapdownleft":
					case "flapupright":
					case "flapupleft":
					default:
						break;
				}
			}
			else
			{
			    if (Process.GetProcessesByName("POWERPNT").Count() > 0)
			    {

			        if (PowerPointApplication != null)
                        foreach (SlideShowWindow slideShowWindow in PowerPointApplication.SlideShowWindows.Cast<SlideShowWindow>())
			            {
			                switch (gestureName.ToLower())
			                {
			                    case "breaststrokeright":
			                        slideShowWindow.View.Next();
			                        break;
			                    case "breaststrokeleft":
			                        slideShowWindow.View.Previous();
			                        break;
			                    case "salute":
			                        EnableMouseTracking = !EnableMouseTracking;
			                        if (!EnableMouseTracking && MouseTrackingActive)
			                        {
			                            MouseTrackingActive = false;
			                        }
			                        break;
			                    case "waxoff":
			                    case "waxon":
			                    case "flapdownright":
			                    case "flapdownleft":
			                    case "flapupright":
			                    case "flapupleft":
			                    default:
			                        break;
			                }
			            }
			    }
			}
		}

		void controller_GesturesLoaded(List<string> gestureNames)
		{
			while (LoadedGestures.Count > 0)
				LoadedGestures.RemoveAt(0);

			foreach (string gestureName in gestureNames)
			{
				LoadedGestures.Add(gestureName);
			}
			OnPropertyChanged(() => LoadedGestures);
		}


		void controller_JointProximityTriggerChanged(JointProximityTrigger trigger)
		{
			if (EnableMouseTracking)
			{
				if (MouseTrackingActive)
				{
					if (trigger.JointA == JointID.HipLeft && trigger.JointB == JointID.HandLeft)
					{

						HandOnLeftHip = trigger.active;
						OnPropertyChanged(() => HandOnLeftHip);
						Win32.DoMouseClick(trigger.active);
					}
				}

				if (trigger.JointA == JointID.ShoulderRight && trigger.JointB == JointID.HandLeft)
				{
					if (trigger.active)
					{
						MouseTrackingActive = !MouseTrackingActive;

						//	mouseup just in case
						if (!MouseTrackingActive)
							Win32.DoMouseClick(false);
					}
				}
			}
		}

		void controller_TrackedJointChanged(JointID trackedJoint)
		{
			CurrentTrackedJoint = trackedJoint;
		}


		void speech_SpeechRecognized(string message)
		{
			LastGesture = "Voice Command:" + message;
			OnPropertyChanged(() => LastGesture);
		}

		#endregion

	}
}
